#!/usr/bin/env python3
"""
COS+CDN优化的图片增强API
实现GPU服务器与COS内网传输，通过CDN加速用户访问
"""

import os
import time
import uuid
import json
import logging
import requests
from datetime import datetime
from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename
from qcloud_cos import CosConfig, CosS3Client
from qcloud_cos.cos_exception import CosServiceError
import hashlib
import json

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

app = Flask(__name__)

# 配置信息
class Config:
    # GPU服务器配置 - 从backend_servers.json动态读取
    BACKEND_SERVERS_FILE = "api-gateway/backend_servers.json"
    
    # COS配置 (动态地域配置)
    COS_SECRET_ID = os.getenv('COS_SECRET_ID', 'AKIDAQTJzVotlSwDH8p2MZw9E855uZHo8F9u')
    COS_SECRET_KEY = os.getenv('COS_SECRET_KEY', 'jGav66wa9XkldKp9JI7kEdqulPq45vZ0')
    
    # 动态地域配置 - 根据GPU服务器地域自动选择COS桶
    GPU_REGION = os.getenv('GPU_REGION', 'ap-beijing')  # 默认北京
    COS_BUCKET_PREFIX = os.getenv('COS_BUCKET_PREFIX', 'photoenhancei')
    
    # 地域映射配置 - 主要支持4个地域
    REGION_MAPPING = {
        # 主要支持地域 (按优先级排序)
        'ap-beijing': {
            'cos_region': 'ap-beijing',
            'bucket_suffix': 'bj',
            'internal_ip_pattern': '10.2.'
        },
        'ap-shanghai': {
            'cos_region': 'ap-shanghai', 
            'bucket_suffix': 'sh',
            'internal_ip_pattern': '10.3.'
        },
        'ap-guangzhou': {
            'cos_region': 'ap-guangzhou',
            'bucket_suffix': 'gz', 
            'internal_ip_pattern': '10.1.'
        },
        'ap-chengdu': {
            'cos_region': 'ap-chengdu',
            'bucket_suffix': 'cd',
            'internal_ip_pattern': '10.4.'
        }
    }
    
    @classmethod
    def get_cos_config(cls):
        """动态获取COS配置"""
        # 根据GPU服务器内网IP自动检测地域
        detected_region = cls._detect_region_by_ip()
        
        if detected_region in cls.REGION_MAPPING:
            region_config = cls.REGION_MAPPING[detected_region]
            cos_region = region_config['cos_region']
            bucket_suffix = region_config['bucket_suffix']
        else:
            # 使用环境变量或默认配置
            cos_region = cls.GPU_REGION
            bucket_suffix = cos_region.split('-')[-1][:2]  # 取地域简称
        
        # 动态生成存储桶名称
        cos_bucket = f"{cls.COS_BUCKET_PREFIX}-{bucket_suffix}-1259206939"
        
        # 动态生成内网域名
        cos_internal_domain = f"{cos_bucket}.cos-internal.{cos_region}.myqcloud.com"
        
        return {
            'bucket': cos_bucket,
            'region': cos_region,
            'internal_domain': cos_internal_domain,
            'detected_region': detected_region
        }
    
    @classmethod
    def _detect_region_by_ip(cls):
        """根据内网IP自动检测地域"""
        ip = cls.get_gpu_server_ip()
        
        # 如果无法获取GPU服务器IP，返回默认地域
        if not ip:
            logger.warning("无法获取GPU服务器IP，使用默认地域")
            return cls.GPU_REGION
        
        for region, config in cls.REGION_MAPPING.items():
            if ip.startswith(config['internal_ip_pattern']):
                return region
        
        # 如果无法自动检测，返回默认地域
        return cls.GPU_REGION
    
    # CDN配置
    CDN_DOMAIN = "cdn.gongjuxiang.work"
    
    # 文件存储路径
    UPLOAD_FOLDER = "/tmp/uploads"
    PROCESSED_FOLDER = "/tmp/processed"
    
    # 允许的文件类型
    ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'}
    
    # 文件大小限制 (100MB)
    MAX_FILE_SIZE = 100 * 1024 * 1024
    
    @classmethod
    def get_gpu_server_ip(cls):
        """从backend_servers.json动态获取GPU服务器IP"""
        try:
            with open(cls.BACKEND_SERVERS_FILE, 'r') as f:
                servers = json.load(f)
                if servers and len(servers) > 0:
                    # 返回第一个健康的服务器IP
                    return servers[0]['ip']
                else:
                    logger.error("backend_servers.json中没有找到GPU服务器")
                    return None
        except Exception as e:
            logger.error(f"读取backend_servers.json失败: {e}")
            return None

# 动态初始化COS客户端
def get_cos_client():
    """动态获取COS客户端"""
    cos_config_data = Config.get_cos_config()
    
    cos_config = CosConfig(
        Region=cos_config_data['region'],
        SecretId=Config.COS_SECRET_ID,
        SecretKey=Config.COS_SECRET_KEY,
        Domain=cos_config_data['internal_domain']  # 使用内网域名，避免流量费
    )
    
    return CosS3Client(cos_config), cos_config_data

# 初始化COS客户端
cos_client, cos_config_data = get_cos_client()

# 创建必要的目录
os.makedirs(Config.UPLOAD_FOLDER, exist_ok=True)
os.makedirs(Config.PROCESSED_FOLDER, exist_ok=True)

def allowed_file(filename):
    """检查文件类型是否允许"""
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in Config.ALLOWED_EXTENSIONS

def generate_file_key(filename, user_id=None):
    """生成COS存储的文件键"""
    timestamp = int(time.time())
    file_hash = hashlib.md5(filename.encode()).hexdigest()[:8]
    if user_id:
        return f"uploads/{user_id}/{timestamp}_{file_hash}_{secure_filename(filename)}"
    return f"uploads/public/{timestamp}_{file_hash}_{secure_filename(filename)}"

def upload_to_cos(file_path, file_key):
    """上传文件到COS (内网传输)"""
    try:
        start_time = time.time()
        
        # 获取动态COS配置
        cos_client, cos_config = get_cos_client()
        
        response = cos_client.put_object_from_local_file(
            Bucket=cos_config['bucket'],
            LocalFilePath=file_path,
            Key=file_key,
            ACL='public-read',  # 🔑 关键修复：设置公开读取权限
            Metadata={
                'upload-time': str(int(time.time())),
                'source': 'gpu-server',
                'region': cos_config['region']
            }
        )
        
        upload_time = time.time() - start_time
        logger.info(f"文件上传到COS成功: {file_key}, 耗时: {upload_time:.2f}s")
        
        return {
            'success': True,
            'file_key': file_key,
            'upload_time': upload_time,
            'cos_url': f"https://{cos_config['internal_domain']}/{file_key}",
            'region': cos_config['region'],
            'bucket': cos_config['bucket']
        }
        
    except CosServiceError as e:
        logger.error(f"COS上传失败: {e}")
        return {
            'success': False,
            'error': f"COS上传失败: {e.get_error_code()}"
        }

def download_from_cos(file_key, local_path):
    """从COS下载文件 (内网传输)"""
    try:
        start_time = time.time()
        
        # 获取动态COS配置
        cos_client, cos_config = get_cos_client()
        
        response = cos_client.get_object(
            Bucket=cos_config['bucket'],
            Key=file_key,
            ResponseContentDisposition='attachment'
        )
        
        # 保存到本地
        with open(local_path, 'wb') as f:
            # 直接写入响应体内容
            f.write(response['Body'].get_raw_stream().read())
        
        download_time = time.time() - start_time
        logger.info(f"从COS下载文件成功: {file_key}, 耗时: {download_time:.2f}s")
        
        return {
            'success': True,
            'download_time': download_time
        }
        
    except CosServiceError as e:
        logger.error(f"COS下载失败: {e}")
        return {
            'success': False,
            'error': f"COS下载失败: {e.get_error_code()}"
        }

def get_cdn_url(file_key):
    """生成CDN访问URL"""
    return f"https://{Config.CDN_DOMAIN}/{file_key}"

def process_image_with_gpu(file_path, output_path, tile_size=400, quality_level='high'):
    """调用GPU服务器处理图片"""
    try:
        start_time = time.time()
        
        # 准备请求数据
        files = {
            'file': (os.path.basename(file_path), open(file_path, 'rb'), 'image/jpeg')
        }
        
        data = {
            'tile_size': str(tile_size),
            'quality_level': quality_level
        }
        
        # 发送到GPU服务器 (动态IP)
        gpu_server_ip = Config.get_gpu_server_ip()
        if not gpu_server_ip:
            return {
                'success': False,
                'error': '无法获取GPU服务器IP'
            }
        gpu_url = f"http://{gpu_server_ip}:8000/api/v1/enhance"
        
        logger.info(f"发送图片处理请求到GPU服务器: {gpu_url}")
        
        response = requests.post(
            gpu_url,
            files=files,
            data=data,
            timeout=300  # 5分钟超时
        )
        
        files['file'][1].close()  # 关闭文件
        
        if response.status_code == 200:
            # 保存处理后的图片
            with open(output_path, 'wb') as f:
                f.write(response.content)
            
            processing_time = time.time() - start_time
            logger.info(f"GPU处理完成，耗时: {processing_time:.2f}s")
            
            return {
                'success': True,
                'processing_time': processing_time,
                'output_size': os.path.getsize(output_path)
            }
        else:
            logger.error(f"GPU处理失败: {response.status_code}")
            return {
                'success': False,
                'error': f"GPU处理失败: {response.status_code}"
            }
            
    except Exception as e:
        logger.error(f"GPU处理异常: {e}")
        return {
            'success': False,
            'error': f"GPU处理异常: {str(e)}"
        }

@app.route('/api/v1/enhance', methods=['POST'])
def enhance_image():
    """
    COS+CDN优化的图片增强API
    流程: 上传到COS -> GPU处理 -> 上传结果到COS -> 返回CDN链接
    """
    try:
        logger.info("收到COS+CDN优化的图片增强请求")
        
        # 检查文件上传 (支持 'file' 和 'image' 字段)
        file = None
        if 'file' in request.files:
            file = request.files['file']
        elif 'image' in request.files:
            file = request.files['image']
        else:
            return jsonify({
                'success': False,
                'error': '没有上传文件'
            }), 400
        if file.filename == '':
            return jsonify({
                'success': False,
                'error': '文件名为空'
            }), 400
        
        if not allowed_file(file.filename):
            return jsonify({
                'success': False,
                'error': f'不支持的文件类型，仅支持: {", ".join(Config.ALLOWED_EXTENSIONS)}'
            }), 400
        
        # 获取参数
        tile_size = int(request.form.get('tile_size', 400))
        quality_level = request.form.get('quality_level', 'high')
        user_id = request.form.get('user_id', 'anonymous')
        session_id = request.headers.get('X-Session-ID') or request.form.get('session_id')
        
        # 生成任务ID
        task_id = f"task_{uuid.uuid4().hex[:16]}"
        
        # 记录开始时间
        total_start_time = time.time()
        
        # 1. 保存上传的文件
        upload_filename = secure_filename(file.filename)
        upload_path = os.path.join(Config.UPLOAD_FOLDER, f"{task_id}_{upload_filename}")
        file.save(upload_path)
        
        file_size = os.path.getsize(upload_path)
        logger.info(f"文件保存成功: {upload_filename}, 大小: {file_size} bytes")
        
        # 2. 上传原始图片到COS (内网传输)
        original_file_key = generate_file_key(f"original_{upload_filename}", user_id)
        cos_upload_result = upload_to_cos(upload_path, original_file_key)
        
        if not cos_upload_result['success']:
            os.remove(upload_path)
            return jsonify({
                'success': False,
                'error': f"原始图片上传失败: {cos_upload_result['error']}"
            }), 500
        
        # 3. 从COS下载图片到GPU服务器 (内网传输)
        gpu_input_path = os.path.join(Config.UPLOAD_FOLDER, f"gpu_input_{task_id}_{upload_filename}")
        cos_download_result = download_from_cos(original_file_key, gpu_input_path)
        
        if not cos_download_result['success']:
            os.remove(upload_path)
            return jsonify({
                'success': False,
                'error': f"图片下载失败: {cos_download_result['error']}"
            }), 500
        
        # 4. GPU处理图片
        output_filename = f"enhanced_{upload_filename}"
        gpu_output_path = os.path.join(Config.PROCESSED_FOLDER, f"{task_id}_{output_filename}")
        
        gpu_result = process_image_with_gpu(
            gpu_input_path, 
            gpu_output_path, 
            tile_size, 
            quality_level
        )
        
        if not gpu_result['success']:
            # 清理临时文件
            for path in [upload_path, gpu_input_path]:
                if os.path.exists(path):
                    os.remove(path)
            return jsonify({
                'success': False,
                'error': f"GPU处理失败: {gpu_result['error']}"
            }), 500
        
        # 5. 上传处理后的图片到COS (内网传输)
        enhanced_file_key = generate_file_key(f"enhanced_{output_filename}", user_id)
        enhanced_upload_result = upload_to_cos(gpu_output_path, enhanced_file_key)
        
        if not enhanced_upload_result['success']:
            # 清理临时文件
            for path in [upload_path, gpu_input_path, gpu_output_path]:
                if os.path.exists(path):
                    os.remove(path)
            return jsonify({
                'success': False,
                'error': f"处理后图片上传失败: {enhanced_upload_result['error']}"
            }), 500
        
        # 6. 生成CDN访问链接
        cdn_url = get_cdn_url(enhanced_file_key)
        
        # 计算总耗时
        total_time = time.time() - total_start_time
        
        # 清理临时文件
        for path in [upload_path, gpu_input_path, gpu_output_path]:
            if os.path.exists(path):
                os.remove(path)
        
        # 返回结果
        result = {
            'success': True,
            'task_id': task_id,
            'enhanced_image': cdn_url,  # CDN链接，用户访问更快
            'cos_url': f"https://{cos_config_data['internal_domain']}/{enhanced_file_key}",  # COS直链
            'performance': {
                'total_time': total_time,
                'upload_time': cos_upload_result['upload_time'],
                'download_time': cos_download_result['download_time'],
                'processing_time': gpu_result['processing_time'],
                'enhanced_upload_time': enhanced_upload_result['upload_time'],
                'file_size_original': file_size,
                'file_size_enhanced': gpu_result['output_size'],
                'compression_ratio': round(file_size / gpu_result['output_size'], 2) if gpu_result['output_size'] > 0 else 0
            },
            'metadata': {
                'original_file_key': original_file_key,
                'enhanced_file_key': enhanced_file_key,
                'tile_size': tile_size,
                'quality_level': quality_level,
                'user_id': user_id,
                'session_id': session_id,
                'timestamp': datetime.now().isoformat()
            }
        }
        
        logger.info(f"图片增强完成: {task_id}, 总耗时: {total_time:.2f}s, CDN链接: {cdn_url}")
        
        return jsonify(result)
        
    except Exception as e:
        logger.error(f"图片增强异常: {e}")
        return jsonify({
            'success': False,
            'error': f'处理异常: {str(e)}'
        }), 500

@app.route('/api/v1/performance', methods=['GET'])
def get_performance_stats():
    """获取性能统计信息"""
    # 获取动态COS配置
    cos_config_data = Config.get_cos_config()
    
    return jsonify({
        'cos_config': {
            'bucket': cos_config_data['bucket'],
            'region': cos_config_data['region'],
            'internal_domain': cos_config_data['internal_domain'],
            'cdn_domain': Config.CDN_DOMAIN,
            'detected_region': cos_config_data['detected_region']
        },
        'gpu_server': {
            'internal_ip': Config.get_gpu_server_ip(),
            'status': 'connected',
            'region': cos_config_data['detected_region']
        },
        'architecture': {
            'description': '多地域COS+CDN优化架构',
            'benefits': [
                'GPU服务器与COS内网传输，无流量费',
                'CDN加速用户访问',
                '自动负载均衡',
                '高可用性',
                '多地域支持，自动地域检测'
            ],
            'supported_regions': list(Config.REGION_MAPPING.keys())
        }
    })

@app.route('/api/v1/upload/presigned-url', methods=['POST'])
def generate_presigned_url():
    """
    生成COS预签名上传URL
    允许前端直接上传到COS，避免双重上传
    """
    try:
        # 获取参数
        data = request.get_json()
        user_id = data.get('user_id', 'anonymous')
        file_type = data.get('file_type', 'image/jpeg')
        file_size = data.get('file_size', 0)
        filename = data.get('filename', f"{uuid.uuid4().hex}.jpg")
        
        # 验证文件大小（限制10MB）
        if file_size > 10 * 1024 * 1024:
            return jsonify({
                'success': False,
                'error': '文件大小不能超过10MB'
            }), 400
        
        # 验证文件类型
        allowed_types = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']
        if file_type not in allowed_types:
            return jsonify({
                'success': False,
                'error': f'不支持的文件类型，仅支持: {", ".join(allowed_types)}'
            }), 400
        
        # 生成文件键
        file_extension = filename.split('.')[-1] if '.' in filename else 'jpg'
        file_key = f"uploads/{user_id}/{uuid.uuid4().hex}.{file_extension}"
        
        # 获取COS配置
        cos_config_data = Config.get_cos_config()
        
        # 初始化COS客户端
        cos_config = CosConfig(
            Region=cos_config_data['region'],
            SecretId=Config.COS_SECRET_ID,
            SecretKey=Config.COS_SECRET_KEY
        )
        cos_client = CosS3Client(cos_config)
        
        # 生成预签名URL（使用公网域名，设置公开读取权限）
        presigned_url = cos_client.get_presigned_url(
            Method='PUT',
            Bucket=cos_config_data['bucket'],
            Key=file_key,
            Expired=3600,  # 1小时有效期
            Headers={
                'Content-Type': file_type,
                'x-cos-acl': 'public-read'  # 🔑 关键修复：设置公开读取权限
            }
        )
        
        logger.info(f"生成预签名URL成功: {file_key}, 用户: {user_id}")
        
        return jsonify({
            'success': True,
            'presigned_url': presigned_url,
            'file_key': file_key,
            'expires_in': 3600,
            'bucket': cos_config_data['bucket'],
            'region': cos_config_data['region']
        })
        
    except Exception as e:
        logger.error(f"生成预签名URL失败: {str(e)}")
        return jsonify({
            'success': False,
            'error': f"生成预签名URL失败: {str(e)}"
        }), 500

@app.route('/api/v1/enhance-by-key', methods=['POST'])
def enhance_image_by_key():
    """
    通过file_key处理图片（不需要上传文件）
    配合预签名URL使用
    """
    try:
        # 获取参数
        data = request.get_json() if request.is_json else request.form
        file_key = data.get('file_key')
        tile_size = int(data.get('tile_size', 400))
        quality_level = data.get('quality_level', 'high')
        user_id = data.get('user_id', 'anonymous')
        
        if not file_key:
            return jsonify({
                'success': False,
                'error': '缺少file_key参数'
            }), 400
        
        logger.info(f"收到通过file_key处理图片的请求: {file_key}")
        
        # 生成任务ID
        task_id = f"task_{uuid.uuid4().hex[:16]}"
        
        # 构建图片的完整URL信息
        cos_config_data = Config.get_cos_config()
        image_cos_url = f"https://{cos_config_data['internal_domain']}/{file_key}"
        image_cdn_url = f"https://{Config.CDN_DOMAIN}/{file_key}"
        
        # 直接通知GPU服务器处理（传递file_key）
        gpu_server_ip = Config.get_gpu_server_ip()
        
        # 详细日志输出
        logger.info("=" * 80)
        logger.info("🔄 预签名URL流程 - 图片处理请求")
        logger.info("=" * 80)
        logger.info("📁 用户上传的原始图片信息:")
        logger.info(f"  🔑 COS文件键: {file_key}")
        logger.info(f"  📂 存储路径: uploads/{user_id}/目录")
        logger.info("")
        logger.info("🌐 上传到COS桶的图片URL (处理前):")
        logger.info(f"  🔗 COS内网URL: {image_cos_url}")
        logger.info(f"  🌍 CDN公网URL: {image_cdn_url}")
        logger.info("")
        logger.info("📡 发送给GPU服务器的处理请求:")
        logger.info(f"  🎯 目标GPU服务器: {gpu_server_ip}:8000")
        logger.info(f"  📊 处理参数: tile_size={tile_size}, quality_level={quality_level}")
        logger.info(f"  🆔 任务ID: {task_id}")
        logger.info("=" * 80)
        if not gpu_server_ip:
            return jsonify({
                'success': False,
                'error': '无法获取GPU服务器IP'
            }), 500
        gpu_url = f"http://{gpu_server_ip}:8000/api/v1/enhance-by-cos-key"
        
        logger.info(f"📡 发送处理请求到GPU服务器: {gpu_url}")
        
        response = requests.post(
            gpu_url,
            json={
                'cos_file_key': file_key,
                'tile_size': tile_size,
                'quality_level': quality_level
            },
            timeout=300  # 5分钟超时
        )
        
        if response.status_code == 200:
            result = response.json()
            
            if result.get('success'):
                logger.info("=" * 80)
                logger.info("✅ GPU服务器处理完成 - 返回结果")
                logger.info("=" * 80)
                logger.info("🖼️ GPU服务器返回的处理后图片URL:")
                logger.info(f"  🚀 结果CDN URL: {result.get('cdn_url')}")
                logger.info(f"  📂 存储路径: processed/目录")
                logger.info("")
                logger.info("📊 处理性能统计:")
                logger.info(f"  🆔 任务ID: {result.get('task_id', task_id)}")
                logger.info(f"  ⏱️ 下载时间: {result.get('download_time', 0):.2f}s")
                logger.info(f"  🔧 处理时间: {result.get('processing_time', 0):.2f}s")
                logger.info(f"  ⬆️ 上传时间: {result.get('upload_time', 0):.2f}s")
                logger.info(f"  🕐 总时间: {result.get('total_time', 0):.2f}s")
                logger.info("")
                logger.info("🔄 流程总结:")
                logger.info(f"  1️⃣ 用户上传 → COS桶 (uploads/目录)")
                logger.info(f"  2️⃣ GPU处理 → 增强图片")
                logger.info(f"  3️⃣ 结果上传 → COS桶 (processed/目录)")
                logger.info(f"  4️⃣ 返回URL → 前端显示")
                logger.info("=" * 80)
                
                return jsonify({
                    'success': True,
                    'cdn_url': result.get('cdn_url'),
                    'task_id': result.get('task_id', task_id),
                    'download_time': result.get('download_time', 0),
                    'processing_time': result.get('processing_time', 0),
                    'upload_time': result.get('upload_time', 0),
                    'total_time': result.get('total_time', 0)
                })
            else:
                logger.error("=" * 60)
                logger.error("❌ GPU服务器处理失败:")
                logger.error(f"  📝 错误信息: {result.get('error')}")
                logger.error("=" * 60)
                return jsonify({
                    'success': False,
                    'error': f"GPU处理失败: {result.get('error')}"
                }), 500
        else:
            logger.error("=" * 60)
            logger.error("❌ GPU服务器响应错误:")
            logger.error(f"  📊 状态码: {response.status_code}")
            logger.error(f"  📝 响应内容: {response.text}")
            logger.error("=" * 60)
            return jsonify({
                'success': False,
                'error': f"GPU处理失败: {response.status_code}"
            }), 500
            
    except Exception as e:
        logger.error(f"处理异常: {str(e)}")
        return jsonify({
            'success': False,
            'error': f"处理异常: {str(e)}"
        }), 500

@app.route('/health', methods=['GET'])
def health_check():
    """健康检查接口"""
    return jsonify({
        'status': 'healthy',
        'timestamp': datetime.now().isoformat(),
        'cos_connection': 'connected',
        'gpu_server': Config.get_gpu_server_ip()
    })

if __name__ == '__main__':
    logger.info("启动多地域COS+CDN优化的图片增强API服务")
    
    # 获取动态配置
    cos_config_data = Config.get_cos_config()
    
    gpu_server_ip = Config.get_gpu_server_ip()
    logger.info(f"GPU服务器IP: {gpu_server_ip}")
    logger.info(f"检测到的地域: {cos_config_data['detected_region']}")
    logger.info(f"COS存储桶: {cos_config_data['bucket']}")
    logger.info(f"COS地域: {cos_config_data['region']}")
    logger.info(f"COS内网域名: {cos_config_data['internal_domain']}")
    logger.info(f"CDN域名: {Config.CDN_DOMAIN}")
    logger.info(f"支持的地域: {list(Config.REGION_MAPPING.keys())}")
    
    app.run(host='0.0.0.0', port=9000, debug=False)
